---
title: "Primitive Types"
description: "Primitive Data Types in ReScript"
canonical: "/docs/manual/primitive-types"
section: "Language Features"
order: 4
---

# Primitive Types

ReScript comes with the familiar primitive types like `string`, `int`, `float`, etc.

{/* TODO: doc unit */}

## String

ReScript `string`s are delimited using **double** quotes (single quotes are reserved for the character type below).

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let greeting = "Hello world!"
let multilineGreeting = "Hello
 world!"
```

```js
var greeting = "Hello world!";
var multilineGreeting = "Hello\n world!";
```

</CodeTab>

To concatenate strings, use `++`:

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let greetings = "Hello " ++ "world!"
```

```js
var greetings = "Hello world!";
```

</CodeTab>

### String Interpolation

There's a special syntax for string that allows

- multiline string just like before
- no special character escaping
- Interpolation

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let name = "Joe"

let greeting = `Hello
World
👋
${name}
`
```

```js
var name = "Joe";

var greeting = "Hello\nWorld\n👋\n" + name + "\n";
```

</CodeTab>

This is just like JavaScript's backtick string interpolation, except without needing to escape special characters.

### Usage

See the familiar `String` API in the [API docs](/docs/manual/api/stdlib/string). Since a ReScript string maps to a JavaScript string, you can mix & match the string operations in all standard libraries.

### Tips & Tricks

**You have a good type system now!** In an untyped language, you'd often overload the meaning of string by using it as:

- a unique id: `var BLUE_COLOR = "blue"`
- an identifier into a data structure: `var BLUE = "blue" var RED = "red" var colors = [BLUE, RED]`
- the name of an object field: `person["age"] = 24`
- an enum: `if (audio.canPlayType() === 'probably') {...}` [(ಠ_ಠ)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType#Return_value)
- other crazy patterns you'll soon find horrible, after getting used to ReScript's alternatives.

The more you overload the poor string type, the less the type system (or a teammate) can help you! ReScript provides concise, fast and maintainable types & data structures alternatives to the use-cases above (e.g. variants, in a later section).

## Char

ReScript has a type for a string with a single letter:

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let firstLetterOfAlphabet = 'a'
```

```js
var firstLetterOfAlphabet = /* "a" */ 97;
```

</CodeTab>

**Note**: Char doesn't support Unicode or UTF-8 and is therefore not recommended.

To convert a String to a Char, use `String.get("a", 0)`. To convert a Char to a String, use `String.make(1, 'a')`.

## Regular Expression

ReScript regular expressions compile cleanly to their JavaScript counterpart:

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let r = /b/g
```

```js
let r = /b/g;
```

</CodeTab>

A regular expression like the above has the type `RegExp.t`. The [RegExp](/docs/manual/api/stdlib/regexp) module contains the regular expression helpers you have seen in JS.

## Boolean

A ReScript boolean has the type `bool` and can be either `true` or `false`. Common operations:

- `&&`: logical and.
- `||`: logical or.
- `!`: logical not.
- `<=`, `>=`, `<`, `>`
- `==`: structural equal, compares data structures deeply. `(1, 2) == (1, 2)` is `true`. Convenient, but use with caution.
- `===`: referential equal, compares shallowly. `(1, 2) === (1, 2)` is `false`. `let myTuple = (1, 2); myTuple === myTuple` is `true`.
- `!=`: structural unequal.
- `!==`: referential unequal.

ReScript's `true/false` compiles into a JavaScript `true/false`.

## Integers

32-bits, truncated when necessary. We provide the usual operations on them: `+`, `-`, `*`, `/`, etc. See [Int](/docs/manual/api/stdlib/int) for helper functions.

**Be careful when you bind to JavaScript numbers!** Since ReScript integers have a much smaller range than JavaScript numbers, data might get lost when dealing with large numbers. In those cases it’s much safer to bind the numbers as **float**. Be extra mindful of this when binding to JavaScript Dates and their epoch time.

To improve readability, you may place underscores in the middle of numeric literals such as `1_000_000`. Note that underscores can be placed anywhere within a number, not just every three digits.

## Floats

Float requires other operators: `+.`, `-.`, `*.`, `/.`, etc. Like `0.5 +. 0.6`. See [Float](/docs/manual/api/stdlib/float) for helper functions.

As with integers, you may use underscores within literals to improve readability.

### Int-to-Float Coercion

`int` values can be coerced to `float` with the `:>` (type coercion) operator.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let result = (1 :> float) +. 2.
```

```js
var result = 1 + 2;
```

</CodeTab>

## Big Integers (experimental)

**Since 11.1**

For values which are too large to be represented by Int or Float, there is the `bigint` primitive type.
We provide the usual operations on them: `+`, `-`, `*`, `/`, etc. See [BigInt](/docs/manual/api/stdlib/bigint) for helper functions.

A `bigint` number is denoted by a trailing `n` like so: `42n`.

As `bigint` is a different data type than `int`, it's necessary to open the corresponding module to overload the operators.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
open! BigInt

let a = 9007199254740991n + 9007199254740991n
let b = 2n ** 2n
```

```js
var a = 9007199254740991n + 9007199254740991n;

var p = 2n ** 2n;
```

</CodeTab>

It also supports all the bitwise operations, except unsigned shift right (`>>>`), which is not supported by JS itself for `bigint`s.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
open! BigInt

let a = land(1n, 1n)
let b = lor(1n, 1n)
let c = lxor(1n, 1n)
let d = lnot(1n)
let e = lsl(1n, 1n)
let f = asr(1n, 1n)
```

```js
var Js_bigint = require("./stdlib/js_bigint.js");

var a = 1n & 1n;

var b = 1n | 1n;

var c = 1n ^ 1n;

var d = Js_bigint.lnot(1n);

var e = 1n << 1n;

var f = 1n >> 1n;
```

</CodeTab>

It can also be pattern-matched.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let bigintValue = 1n

switch bigintValue {
| 1n => Console.log("Small bigint")
| 100n => Console.log("Larger bigint")
| _ => Console.log("Other bigint")
}
```

```js
if (1n !== 1n) {
  if (1n !== 100n) {
    console.log("Other bigint");
  } else {
    console.log("Larger bigint");
  }
} else {
  console.log("Small bigint");
}

var bigintValue = 1n;
```

</CodeTab>

## Unit

The `unit` type indicates the absence of a specific value. It has only a single value, `()`, which acts as a placeholder when no other value exists or is needed. It compiles to JavaScript's `undefined` and resembles the `void` type in languages such as C++. What's the point of such a type?

Consider the `Math.random` function. Its type signature is `unit => float`, which means it receives a `unit` as input and calculates a random `float` as output. You use the function like this - `let x = Math.random()`. Notice `()` as the first and only function argument.

Imagine a simplified `Console.log` function that prints a message. Its type signature is `string => unit` and you'd use it like this `Console.log("Hello!")`. It takes a string as input, prints it, and then returns nothing useful. When `unit` is the output of a function it means the function performs some kind of side-effect.

## Unknown

The `unknown` type represents values with contents that are a mystery or are not 100% guaranteed to be what you think they are. It provides type-safety when interacting with data received from an untrusted source. For example, suppose an external function is supposed to return a `string`. It might. But if the documentation is not accurate or the code has bugs, the function could return `null`, an `array`, or something else you weren't expecting.

The ReScript type system helps you avoid run-time crashes and unpredicatable behavior by preventing you from using `unknown` in places that expect a `string` or `int` or some other type. The ReScript core libraries also provide utility functions to help you inspect `unknown` values and access their contents. In some cases you may need a JSON parsing library to convert `unknown` values to types you can safely use.

Consider using `unknown` when receiving data from [external JavaScript functions](./bind-to-js-function.mdx)
